/*
 *
 * Copyright (C) 2012 Walter Lütgenau
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 */
package offset.nodes.client.vdialog.view.instance;

import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.HashSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.jcr.RepositoryException;
import javax.swing.JFrame;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumnModel;
import offset.nodes.client.chooser.view.QueryResultChooserDialog;
import offset.nodes.client.model.Server;
import offset.nodes.client.tree.model.TreeNodePanel;
import offset.nodes.client.tree.model.TreeNodePanelContainer;
import offset.nodes.client.model.TreeNodeUserObject;
import offset.nodes.client.model.DialogContext;
import offset.nodes.client.virtual.model.SimpleQuery;
import offset.nodes.client.vdialog.model.instance.VirtualPageInstance;
import offset.nodes.client.view.SimpleDialog;
import offset.nodes.client.vdialog.model.instance.GetVirtualPageInformation;
import offset.nodes.client.veditor.view.instance.QueryPanel;

/**
 *
 * @author  Walter Lütgenau
 */
public class VirtualPageInstancePanel extends javax.swing.JPanel implements TreeNodePanel {

    protected static final int COLUMN_NAME = 0;
    protected static final int COLUMN_QUERY = 1;
    protected static final int COLUMN_NAME_WIDTH = 80;

    class TextFieldDocumentListener implements DocumentListener {

        public void changedUpdate(DocumentEvent e) {
            validateOkButton();
        }

        public void insertUpdate(DocumentEvent e) {
            validateOkButton();
        }

        public void removeUpdate(DocumentEvent e) {
            validateOkButton();
        }
    }
    TreeNodePanelContainer container = null;
    Server server;
    TextFieldDocumentListener textFieldDocumentListener = new TextFieldDocumentListener();
    VirtualPageInstance userObject;
    String templateUuid = null;
    String[] templateQueries;
    
    /** Creates new form FolderPanel
     * @param server the server model
     * @param types the node types repository
     */
    public VirtualPageInstancePanel(Server server) {
        this.server = server;
        initComponents();
        initTable();
    }

    public void initTable() {
        TableColumnModel tcm = secondaryQueryTable.getColumnModel();
        tcm.getColumn(COLUMN_NAME).setPreferredWidth(COLUMN_NAME_WIDTH);
        tcm.getColumn(COLUMN_NAME).setMinWidth(COLUMN_NAME_WIDTH);
        tcm.getColumn(COLUMN_NAME).setMaxWidth(COLUMN_NAME_WIDTH);

       MouseListener ml = new MouseAdapter() {

            public void mousePressed(MouseEvent e) {
              if (e.getClickCount() == 2)
                configureSecondaryQuery(null);
            }
        };
        secondaryQueryTable.addMouseListener(ml);

    }

    private void validateOkButton() {
        boolean ok = true;
        
        if (DialogContext.getInstance() == DialogContext.NEW) {
            if (queryTextField.getText() == null || queryTextField.getText().length() == 0)
                ok = false;

            if (secondaryQueryTable.getModel().getRowCount() > 0)
                for (int row = 0; row < secondaryQueryTable.getModel().getRowCount(); row++) {
                    try {
                        String current = (String) secondaryQueryTable.getModel().getValueAt(row, COLUMN_QUERY);
                        String before = getQuery(this.userObject.getQueries()[row]);
                        if (current.equals(before))
                            ok = false;
                    } catch (RepositoryException ex) {
                        ex.printStackTrace();
                    }
                }
        }

        container.enableOkButton(ok);
    }

    /**
     * Check, if the queries of the template have changed after saving the instance. In that
     * case, return the template queries to allow the user to configure them for the instance.
     *
     * If not, return the already saved instance queries for update.
     * 
     * @return the queries, that shall be displayed to the user
     * @throws RepositoryException
     */
    protected String[] checkQueries() throws RepositoryException {
        String[] instanceQueries = userObject.getQueries();
 
        // some query added or removed
        if (instanceQueries == null || instanceQueries.length != templateQueries.length)
            return templateQueries;

        /* the instance queries and the template queries should have the same
         * secondary queries, but you never know
         */
        final String delimiter = "=";
        HashSet<String> instanceQuerySet = new HashSet<String>();
        for (int i = 0; i < instanceQueries.length; i++) {
            String[] instanceQuery = instanceQueries[i].split(delimiter);
            instanceQuerySet.add(instanceQuery[0]);
        }

        for (int i = 0; i < templateQueries.length; i++) {
            String[] templateQuery = templateQueries[i].split(delimiter);

            if (!instanceQuerySet.contains(templateQuery[0])) // different secondary query
                return templateQueries;
        }

        return instanceQueries;
    }

    /**
     * Retrieve information about the virtual page node of the template
     * 
     * @param uuid
     * @return
     * @throws Exception
     */
    protected GetVirtualPageInformation.Response getVirtualPageInformation(String uuid) throws Exception {
        if (uuid == null)
            return null;
        
        GetVirtualPageInformation.Request request = new GetVirtualPageInformation.Request();
        request.setUuid(uuid);
        
        GetVirtualPageInformation.Response response = (GetVirtualPageInformation.Response) server.sendRequest(request);

        return response;
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        folderNameButtonGroup = new javax.swing.ButtonGroup();
        queryLabel = new javax.swing.JLabel();
        queryTextField = new javax.swing.JTextField();
        queryTextField.getDocument().addDocumentListener(textFieldDocumentListener);
        queryLabel1 = new javax.swing.JLabel();
        queryButton = new javax.swing.JButton();
        jScrollPane1 = new javax.swing.JScrollPane();
        secondaryQueryTable = new javax.swing.JTable();
        queryButton3 = new javax.swing.JButton();
        useAsDefaultCombo = new javax.swing.JCheckBox();
        templateLabel = new javax.swing.JLabel();
        templateTextfield = new javax.swing.JTextField();
        templateButton = new javax.swing.JButton();

        java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("offset/nodes/client/vdialog/view/DialogBundle"); // NOI18N
        queryLabel.setText(bundle.getString("template.templateQueryPanel.query")); // NOI18N

        queryLabel1.setText(bundle.getString("template.templateQueryPanel.secondaryQueries")); // NOI18N

        queryButton.setText(bundle.getString("edit")); // NOI18N
        queryButton.setPreferredSize(new java.awt.Dimension(67, 23));
        queryButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                configurePrimaryQuery(evt);
            }
        });

        secondaryQueryTable.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {

            },
            new String [] {
                "Name", "Query"
            }
        ) {
            Class[] types = new Class [] {
                java.lang.String.class, java.lang.String.class
            };
            boolean[] canEdit = new boolean [] {
                false, false
            };

            public Class getColumnClass(int columnIndex) {
                return types [columnIndex];
            }

            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return canEdit [columnIndex];
            }
        });
        jScrollPane1.setViewportView(secondaryQueryTable);

        queryButton3.setText(bundle.getString("edit")); // NOI18N
        queryButton3.setPreferredSize(new java.awt.Dimension(67, 23));
        queryButton3.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                configureSecondaryQuery(evt);
            }
        });

        useAsDefaultCombo.setText(bundle.getString("template.templateInstancePanel.useAsDefault")); // NOI18N

        templateLabel.setText(bundle.getString("template.templateInstancePanel.template")); // NOI18N

        templateButton.setText("...");
        templateButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                selectTemplate(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addGap(24, 24, 24)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(templateLabel)
                    .addComponent(queryLabel)
                    .addComponent(queryLabel1))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 760, Short.MAX_VALUE)
                    .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                        .addComponent(templateTextfield)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(templateButton))
                    .addComponent(queryTextField)
                    .addGroup(layout.createSequentialGroup()
                        .addGap(299, 299, 299)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                            .addComponent(useAsDefaultCombo)
                            .addComponent(queryButton3, javax.swing.GroupLayout.PREFERRED_SIZE, 75, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(queryButton, javax.swing.GroupLayout.PREFERRED_SIZE, 75, javax.swing.GroupLayout.PREFERRED_SIZE))))
                .addGap(41, 41, 41))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(32, 32, 32)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(templateLabel)
                    .addComponent(templateTextfield, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(templateButton))
                .addGap(43, 43, 43)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(queryTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(queryLabel))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(queryButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(36, 36, 36)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 71, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(queryButton3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(34, 34, 34)
                        .addComponent(useAsDefaultCombo))
                    .addComponent(queryLabel1))
                .addContainerGap(76, Short.MAX_VALUE))
        );
    }// </editor-fold>//GEN-END:initComponents

    private void configureSecondaryQuery(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_configureSecondaryQuery
        int selected = secondaryQueryTable.getSelectedRow();
        if (selected < 0)
            return;

        String queryString = (String) secondaryQueryTable.getModel().getValueAt(selected, COLUMN_QUERY);
        SimpleQuery query = new SimpleQuery();
        query.setQueryParametersFromString(queryString);        
        QueryPanel queryPanel = new QueryPanel(server, userObject.getNodeType(), query, true);
        
        SimpleDialog dialog = new SimpleDialog(new JFrame(), true, queryPanel);
        dialog.setVisible(true);
        if ( dialog.getReturnStatus() == SimpleDialog.OK) {
            secondaryQueryTable.getModel().setValueAt(queryPanel.getQueryParameters().getQueryStringFromQueryParameters(), 
                    selected, COLUMN_QUERY);
            validateOkButton();
        }
}//GEN-LAST:event_configureSecondaryQuery

    private void configurePrimaryQuery(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_configurePrimaryQuery
        SimpleQuery query = new SimpleQuery();
        query.setQueryParametersFromString(queryTextField.getText());        
        QueryPanel queryPanel = new QueryPanel(server, userObject.getNodeType(), query, false);
        
        SimpleDialog dialog = new SimpleDialog(new JFrame(), true, queryPanel);
        dialog.setVisible(true);
        if ( dialog.getReturnStatus() == SimpleDialog.OK) {
            queryTextField.setText(queryPanel.getQueryParameters().getQueryStringFromQueryParameters());
        }
}//GEN-LAST:event_configurePrimaryQuery

    private void selectTemplate(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_selectTemplate
        QueryResultChooserDialog chooser = null;

        try {
             chooser = new QueryResultChooserDialog(new javax.swing.JFrame(), true, server, "//element(*,nodes:templateNode)[@nodes:primaryQuery='" + userObject.getNodeType() + "']");
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }

        chooser.setVisible(true);
        if (chooser.getResult() == SimpleDialog.OK) {
            templateUuid = chooser.getUuid();
            templateTextfield.setText(chooser.getPath());
        }

    }//GEN-LAST:event_selectTemplate

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.ButtonGroup folderNameButtonGroup;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JButton queryButton;
    private javax.swing.JButton queryButton3;
    private javax.swing.JLabel queryLabel;
    private javax.swing.JLabel queryLabel1;
    private javax.swing.JTextField queryTextField;
    private javax.swing.JTable secondaryQueryTable;
    private javax.swing.JButton templateButton;
    private javax.swing.JLabel templateLabel;
    private javax.swing.JTextField templateTextfield;
    private javax.swing.JCheckBox useAsDefaultCombo;
    // End of variables declaration//GEN-END:variables
    public void setPanel(TreeNodeUserObject userObject) {

        try {
            if (userObject == null || !(userObject instanceof VirtualPageInstance))
                return;
            this.userObject = (VirtualPageInstance) userObject;
            if (this.userObject.getTemplateNodeReference() != null) {
                GetVirtualPageInformation.Response response = null;
                try {
                    response = getVirtualPageInformation(this.userObject.getTemplateNodeReference());
                } catch (Exception ex) {
                    Logger.getLogger(VirtualPageInstancePanel.class.getName()).log(Level.SEVERE, null, ex);
                }
                templateUuid = this.userObject.getTemplateNodeReference();
                templateTextfield.setText(response.getPath());
                templateQueries = response.getSecondaryQueries();
                if (templateQueries == null)
                    templateQueries = new String[0];
            }
 
            int row = 0;
            DefaultTableModel table = (DefaultTableModel) secondaryQueryTable.getModel();
            String[] queries = checkQueries();
            if (queries != null && queries.length > 0) {
                for (row = 0; row < queries.length; row++) {
                    String query = queries[row];
                    int index = query.indexOf("=");
                    if (index < 0)
                        continue;
                    String name = query.substring(0, index);
                    String value = query.substring(index + 1);

                    while ( table.getRowCount() <= row)
                        table.addRow((Object[])null);
                    table.setValueAt(name, row, COLUMN_NAME);
                    table.setValueAt(value, row, COLUMN_QUERY);
                }
            }

            int rows = table.getRowCount();
            for (int i = row; i < rows; i++) {
                table.removeRow(row);
            }

            if (this.userObject.getQuery() == null || this.userObject.getQuery().length() == 0) {
                queryTextField.setEnabled(false);
                queryButton.setEnabled(false);
            }
            else {
                queryTextField.setText(this.userObject.getQuery());
                queryTextField.setEnabled(true);
                queryButton.setEnabled(true);
            }

            useAsDefaultCombo.setSelected(this.userObject.isUseAsDefault());
        } catch (RepositoryException ex) {
            ex.printStackTrace();
        }
    }
    
    protected String getQuery(String query) {
        int index = query.indexOf("=");
        if (index < 0)
            return query;

        return query.substring(index + 1);
    }


    public TreeNodeUserObject getUserObject() {
        try {

            userObject.setTemplateNodeReference(templateUuid);
            userObject.setQuery(queryTextField.getText());

            // set secondary Queries
            DefaultTableModel table = (DefaultTableModel) secondaryQueryTable.getModel();
            if (table.getRowCount() > 0)
                try {
                    String[] secondaryQueries = new String[table.getRowCount()];
                    for (int row = 0; row < secondaryQueries.length; row++) {
                        String name = (String) table.getValueAt(row, COLUMN_NAME);
                        String query = (String) table.getValueAt(row, COLUMN_QUERY);

                        secondaryQueries[row] = name + "=" + query;
                    }
                    userObject.setQueries(secondaryQueries);
                } catch (RepositoryException ex) {
                    ex.printStackTrace();
                }
            else
                userObject.setQueries(new String[0]);
            userObject.setUseAsDefault(useAsDefaultCombo.isSelected());
            return userObject;
        } catch (RepositoryException ex) {
            Logger.getLogger(VirtualPageInstancePanel.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }
    }

    public void setContainer(TreeNodePanelContainer container) {
        this.container = container;
    }
}
